"use strict";
/**
 * 表达式取反
 */
Object.defineProperty(exports, "__esModule", { value: true });
var types_1 = require("./types");
var util_1 = require("./util");
// import {print} from './print';
var simplify_1 = require("./simplify");
/**
 * 集合取反
 */
function reverse(oriExp) {
    var _a;
    var exp = simplify_1.simplify(oriExp);
    if (exp.operator === types_1.Operator.FULL) {
        return types_1.EMPTY;
    }
    else if (exp.operator === types_1.Operator.EMPTY) {
        return types_1.FULL;
    }
    var AND = types_1.BoolOperation.AND, OR = types_1.BoolOperation.OR;
    if (util_1.isBoolExpression(exp)) {
        var newOp = exp.operator === OR ? AND : OR;
        return {
            operator: newOp,
            args: exp.args.map(reverse).filter(function (i) { return i !== null; }),
        };
    }
    else {
        var oriOp = exp.operator;
        var EQ = types_1.Operator.EQ, NEQ = types_1.Operator.NEQ, IN = types_1.Operator.IN, NOT_IN = types_1.Operator.NOT_IN, LT = types_1.Operator.LT, GT = types_1.Operator.GT, NGT = types_1.Operator.NGT, NLT = types_1.Operator.NLT;
        var reverseMap = (_a = {},
            _a[EQ] = NEQ,
            _a[NEQ] = EQ,
            _a[IN] = NOT_IN,
            _a[NOT_IN] = IN,
            _a[LT] = NLT,
            _a[GT] = NGT,
            _a[NGT] = GT,
            _a[NLT] = LT,
            _a);
        if (oriOp in reverseMap) {
            return {
                key: exp.key,
                operator: reverseMap[oriOp],
                value: exp.value,
            };
        }
        var RIN = types_1.Operator.RIN, LO_IN_INNER = types_1.Operator.LO_IN_INNER, RO_IN_INNER = types_1.Operator.RO_IN_INNER, O_IN_INNER = types_1.Operator.O_IN_INNER, SEGMENTS_INNER = types_1.Operator.SEGMENTS_INNER;
        if ([RIN, LO_IN_INNER, RO_IN_INNER, O_IN_INNER].includes(oriOp)) {
            var _b = exp.value, left = _b[0], right = _b[1];
            var leftOperator = [LO_IN_INNER, O_IN_INNER].includes(oriOp) ? NGT : LT;
            var rightOperator = [RO_IN_INNER, O_IN_INNER].includes(oriOp) ? NLT : GT;
            return {
                key: exp.key,
                operator: SEGMENTS_INNER,
                value: [
                    {
                        key: exp.key,
                        operator: leftOperator,
                        value: left,
                    },
                    {
                        key: exp.key,
                        operator: rightOperator,
                        value: right,
                    },
                ],
            };
        }
        else {
            // SEGMENTS_INNER
            var reversedSeg = exp.value
                .map(reverse)
                .filter(function (i) { return i !== null; });
            var unionExp = {
                operator: AND,
                args: reversedSeg,
            };
            return simplify_1.simplify(unionExp);
        }
    }
}
exports.reverse = reverse;
